home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * zrgb.c: an openGL-Xlib RGB, zbuffer example program.
- *
- * zrgb is the openGL "after" version of the IrisGL
- * "before" program, ~4Dgifts/examples/grafix/zrgb.c
- *
- * - LEFTMOUSE: move the 3 polygons around a center
- * - Esc key: exit
- *
- * This program demostrates zbuffering 3 intersecting RGB polygons while
- * in doublebuffer mode where, movement of the mouse with the LEFTMOUSE
- * button depressed will, rotate the 3 polygons via compound rotations
- * allowing continuous screen-oriented rotations. (See orient(), and
- * draw_scene() below). Notice that there is no wasted CPU usage when the
- * user moves the mouse out of the window without holding down LEFTMOUSE--
- * there is no "qtest" -type functionality being performed. Hence the
- * program simply blocks on the XNextEvent statement.
- *
- * ratmandu -- ported to openGL, april 93
- */
-
- #include <GL/glx.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <X11/keysym.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
-
- #define TRUE 1
- #define FALSE 0
-
-
- Display *dpy; /* The X server connection */
- Atom del_atom; /* WM_DELETE_WINDOW atom */
- Window glwin; /* handle to the GL window */
- XEvent event;
-
- /* function declarations */
-
- void openwindow(char *);
- void resize_buffer(void);
- void clean_exit(void);
- void initGL(void);
- void orient(void);
- void drawScene(void);
- void drawPolys(void);
-
- static float objmat[16] = {
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0,
- };
-
- int xsize, ysize; /* current size-of-window keepers */
- double scrnaspect; /* aspect ratio value */
- int xpos, ypos, oxpos, oypos; /* old and new mouse position */
-
-
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- int myExpose, myConfigure, myButtPress, myKeyPress;
- int needToDraw = 0; /* don't set this to true until
- we get our first Expose event */
-
-
-
- myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
-
- openwindow(argv[0]);
-
-
- /* start out making the singlebuffer window be our current GL window */
- initGL(); /* do GL init stuff */
-
- /*
- * The event loop.
- */
- while (1) { /* standard logic: get event(s), process event(s) */
-
- XEvent event;
- KeySym keysym;
- char buf[4];
-
- /* this "do while" loop does the `get events' half of the "get events,
- * process events" action of the infinite while. this is to ensure
- * the event queue is always drained before the events that have come
- * in are processed.
- */
- do {
-
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- /* "Expose" events are sort of like "REDRAW" in gl-speak in
- * terms of when a window becomes visible, or a previously
- * invisible part becomes visible.
- */
- case Expose: /* Exposures */
- needToDraw = myExpose = TRUE;
- break;
-
- /* "ConfigNotify" events are like "REDRAW" in terms of changes
- * to a window's size or position.
- */
- case ConfigureNotify: /* Resize GL manually */
- xsize = event.xconfigure.width;
- ysize = event.xconfigure.height;
- needToDraw = myConfigure = TRUE;
- break;
-
- /* Wait for "MotionNotify" events so the queue doesn't fill up
- */
- case MotionNotify:
- myButtPress = TRUE;
- xpos = event.xmotion.x;
- ypos = event.xmotion.y;
- break;
-
- /* "ClientMessage" is generated if the WM itself is being
- * gunned down and sends an exit signal to any running prog.
- */
- case ClientMessage:
- if (event.xclient.data.l[0] == del_atom)
- clean_exit();
- break;
-
- /* "KeyPress" events are those that would be generated before
- * whenever queueing up any KEYBD key via qdevice.
- */
- case KeyPress:
- /* save out which unmodified key (i.e. the key was
- * not modified w/something like "Shift", "Ctrl",
- * or "Alt") got pressed for use below.
- */
- XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
- myKeyPress = TRUE;
- break;
-
- } /* end switch (event.type) */
-
-
- } while (XPending(dpy)); /* end "do { } while".
- * XPending() is like qtest()--it only
- * tells you if there're any events
- * presently in the queue. it does not
- * disturb queue's contents in any way.
- */
-
- /* On an "Expose" event, redraw the affected pop'd or de-iconized window
- */
- if (myExpose) {
- resize_buffer();
- myExpose = FALSE; /* reset flag--queue now empty */
- }
-
- /* On a "ConfigureNotify" event, the GL window has either been moved or
- * resized. Respond accordingly and then redraw its contents.
- */
- if (myConfigure) {
- oxpos = xpos;
- oypos = ypos;
- resize_buffer();
- myConfigure = FALSE; /* reset flag--queue now empty */
- }
-
- if (needToDraw) {
- drawScene();
- needToDraw = FALSE;
- }
-
- /* On a keypress of Esc key, exit program.
- */
- if (myKeyPress) {
- if (keysym == XK_Escape)
- clean_exit();
- }
-
- if (myButtPress) {
- orient();
- drawScene();
- myButtPress = FALSE;
- }
- } /* end while(1) */
-
- } /* end main */
-
-
-
- static int attributeList[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- None };
- static int attributeList2[] = { GLX_RGBA,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- None };
-
-
- static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
- return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
- }
-
- XSizeHints Winhints; /* used to fix window size */
-
-
- /* openwindow -
- * establish connection to X server, get screen info, specify the
- * attributes we want the WM to try to provide, and create the GL window
- */
- void openwindow(char *progname) {
-
- XVisualInfo *vi;
- GLXContext cx;
- Colormap cmap;
- XSizeHints Winhints; /* used to fix window size */
- XSetWindowAttributes swa;
- int scrnnum; /* X screen number */
- int xorig, yorig; /* window (upper-left) origin */
- long scrnheight;
-
-
-
-
- /* define window initial size */
- xorig = 50; yorig = 40;
- xsize = 300; ysize = 240;
- scrnaspect = xsize / (double) ysize;
-
- /* Connect to the X server and get screen info */
- if ((dpy = XOpenDisplay(NULL)) == NULL) {
- fprintf(stderr, "%s: cannot connect to X server %s\n",
- progname, XDisplayName(NULL));
- exit(1);
- }
-
- scrnnum = DefaultScreen(dpy);
- scrnheight = DisplayHeight(dpy, scrnnum);
-
- /* get an appropriate visual */
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
- if (vi == NULL) {
- fprintf(stderr, "Unable to obtain Doublebuffered visual; ");
- fprintf(stderr, "now going for singlebuffer'd...\n");
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
- }
- if (vi == NULL) {
- printf("Unable to obtain Singlebuffered VISUAL(????)\n");
- exit(0);
- }
-
- /* create a GLX context */
- cx = glXCreateContext(dpy, vi, None, GL_TRUE);
-
- /* create a colormap */
- cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
- vi->visual, AllocNone);
-
- /* create a window */
- swa.colormap = cmap;
- swa.border_pixel = 0;
- swa.event_mask = StructureNotifyMask | ButtonPressMask | ExposureMask |
- Button1MotionMask | KeyPressMask; /* express interest in events */;
- glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
- xorig, yorig, xsize, ysize,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
-
- XMapWindow(dpy, glwin);
- XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
-
- /* connect the context to the window */
- glXMakeCurrent(dpy, glwin, cx);
-
- if (!(glwin)) {
- fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
- exit(1);
- }
-
- /* define string that will show up in the window title bar (and icon) */
- XStoreName(dpy, glwin, "z-buffered rgb program");
-
- /* specify the values for the Window Size Hints we want to enforce: this
- * window's aspect ratio needs to stay at 1:1, constrain min and max
- * window size, and specify the initial size of the window.
- */
- Winhints.width = xsize; /* specify desired x/y size of window */
- Winhints.height = ysize;
- Winhints.min_width = xorig; /* define min and max */
- Winhints.max_width = scrnheight-1; /* width and height */
- Winhints.min_height = yorig;
- Winhints.max_height = scrnheight-1;
- Winhints.min_aspect.x = xsize; /* keep aspect to a xsize:ysize ratio */
- Winhints.max_aspect.x = xsize;
- Winhints.min_aspect.y = ysize;
- Winhints.max_aspect.y = ysize;
- Winhints.flags = USSize|PMaxSize|PMinSize|PAspect; /* set the */
- XSetNormalHints(dpy, glwin, &Winhints); /* corresponding flags */
-
- /* express interest in WM killing this app */
- if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
- XSetWMProtocols(dpy, glwin, &del_atom, 1);
-
- return ;
- }
-
-
-
-
- /* window has been moved or resized so update viewport & CTM stuff.
- */
- void resize_buffer() {
-
- XSync(dpy, False); /* STILL NEED THIS????? *//* Need before GL reshape */
- scrnaspect = xsize / (double) ysize;
- glViewport(0, 0, xsize-1, ysize-1);
- }
-
-
-
- /* clean up before exiting
- */
- void clean_exit(void)
- {
- XCloseDisplay(dpy);
- exit(0);
- }
-
-
-
- /* setup all necessary GL initialzation parameters.
- */
- void initGL()
- {
- glEnable(GL_DEPTH_TEST);
- glClearColor(0.16, 0.39, 0.78, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- gluPerspective(400.0, scrnaspect, 30.0, 1000.0);
- }
-
-
- void orient()
- {
- float dx, dy;
-
- glPushMatrix();
- dx = xpos-oxpos;
- dy = oypos-ypos;
- glLoadIdentity();
- glRotatef((float) (0.03*(xpos-oxpos)), 1.0, 0.0, 0.0);
- glRotatef((float) (0.03*(oypos-ypos)), 0.0, 1.0, 0.0);
- glMultMatrixf(objmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
-
- glPopMatrix();
- }
-
-
- void drawScene()
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix();
- glTranslatef(0.0, 0.0, -40.0);
- glMultMatrixf(objmat);
- glRotatef(-220.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
- drawPolys();
- glPopMatrix();
- glFlush ();
- glXSwapBuffers(dpy, glwin);
- }
-
-
- float polygon1[3][3] = { {-10.0, -10.0, 0.0,},
- { 10.0, -10.0, 0.0,},
- {-10.0, 10.0, 0.0,} };
-
- float polygon2[3][3] = { { 0.0, -10.0, -10.0,},
- { 0.0, -10.0, 10.0,},
- { 0.0, 5.0, -10.0,} };
-
- float polygon3[4][3] = { {-10.0, 6.0, 4.0,},
- {-10.0, 3.0, 4.0,},
- { 4.0, -9.0, -10.0,},
- { 4.0, -6.0, -10.0,} };
-
- void drawPolys()
- {
- glBegin(GL_POLYGON);
- glColor4f(0.0, 0.0, 0.0, 0.0);
- glVertex3fv(&polygon1[0][0]);
- glColor4f(0.5, 0.5, 0.5, 0.0);
- glVertex3fv(&polygon1[1][0]);
- glColor4f(1.0, 1.0, 1.0, 0.0);
- glVertex3fv(&polygon1[2][0]);
- glEnd();
-
- glBegin(GL_POLYGON);
- glColor4f(1.0, 1.0, 0.0, 0.0);
- glVertex3fv(&polygon2[0][0]);
- glColor4f(0.0, 1.0, 0.5, 0.0);
- glVertex3fv(&polygon2[1][0]);
- glColor4f(0.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon2[2][0]);
- glEnd();
-
- glBegin(GL_POLYGON);
- glColor4f(1.0, 1.0, 0.0, 0.0);
- glVertex3fv(&polygon3[0][0]);
- glColor4f(1.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[1][0]);
- glColor4f(0.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[2][0]);
- glColor4f(1.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[3][0]);
- glEnd();
-
- }
-